
#include "gps530z.h"
#include "main.h"
#include "usart.h"
#include "i2c.h"
#define AHT20_I2C_IDX HI_I2C_IDX_1

#define AHT20_STARTUP_TIME     20 // 上电启动时间
#define AHT20_CALIBRATION_TIME 40 // 初始化（校准）时间
#define AHT20_MEASURE_TIME     75 // 测量时间

#define AHT20_DEVICE_ADDR   0x38
#define AHT20_READ_ADDR     ((0x38<<1)|0x1)
#define AHT20_WRITE_ADDR    ((0x38<<1)|0x0)

#define AHT20_CMD_CALIBRATION       0xBE // 初始化（校准）命令
#define AHT20_CMD_CALIBRATION_ARG0  0x08
#define AHT20_CMD_CALIBRATION_ARG1  0x00
#define HI_ERR_SUCCESS 0
#define HI_ERR_FAILURE 1
/**
 * 传感器在采集时需要时间,主机发出测量指令（0xAC）后，延时75毫秒以上再读取转换后的数据并判断返回的状态位是否正常。
 * 若状态比特位[Bit7]为0代表数据可正常读取，为1时传感器为忙状态，主机需要等待数据处理完成。
 **/
#define AHT20_CMD_TRIGGER       0xAC // 触发测量命令
#define AHT20_CMD_TRIGGER_ARG0  0x33
#define AHT20_CMD_TRIGGER_ARG1  0x00

// 用于在无需关闭和再次打开电源的情况下，重新启动传感器系统，软复位所需时间不超过20 毫秒
#define AHT20_CMD_RESET      0xBA // 软复位命令

#define AHT20_CMD_STATUS     0x71 // 获取状态命令

/**
 * STATUS 命令回复：
 * 1. 初始化后触发测量之前，STATUS 只回复 1B 状态值；
 * 2. 触发测量之后，STATUS 回复6B： 1B 状态值 + 2B 湿度 + 4b湿度 + 4b温度 + 2B 温度
 *      RH = Srh / 2^20 * 100%
 *      T  = St  / 2^20 * 200 - 50
 **/
#define AHT20_STATUS_BUSY_SHIFT 7       // bit[7] Busy indication
#define AHT20_STATUS_BUSY_MASK  (0x1<<AHT20_STATUS_BUSY_SHIFT)
#define AHT20_STATUS_BUSY(status) ((status & AHT20_STATUS_BUSY_MASK) >> AHT20_STATUS_BUSY_SHIFT)

#define AHT20_STATUS_MODE_SHIFT 5       // bit[6:5] Mode Status
#define AHT20_STATUS_MODE_MASK  (0x3<<AHT20_STATUS_MODE_SHIFT)
#define AHT20_STATUS_MODE(status) ((status & AHT20_STATUS_MODE_MASK) >> AHT20_STATUS_MODE_SHIFT)

                                        // bit[4] Reserved
#define AHT20_STATUS_CALI_SHIFT 3       // bit[3] CAL Enable
#define AHT20_STATUS_CALI_MASK  (0x1<<AHT20_STATUS_CALI_SHIFT)
#define AHT20_STATUS_CALI(status) ((status & AHT20_STATUS_CALI_MASK) >> AHT20_STATUS_CALI_SHIFT)
                                        // bit[2:0] Reserved

#define AHT20_STATUS_RESPONSE_MAX 6

#define AHT20_RESOLUTION            (1<<20)  // 2^20

#define AHT20_MAX_RETRY 10



/*************************************
功能：发送数据到Gps模块
作者：xinxue
日期：2023.8.31
参数：cmd  AT命令
返回值：无
**************************************/
void SendAtToGps(char *cmd)
{
	int len = strlen(cmd);
	HAL_UART_Transmit(&huart2, (uint8_t *)cmd, len,0xff);
	//int ret = hi_uart_write(HI_UART_IDX_1, (unsigned char *)cmd, len);
	// printf("ret:%d", ret);
}
/*************************************
功能：Gps模块初始化
作者：xinxue
日期：2023.8.31
参数：无
返回值：无
**************************************/
void Gps_Init()
{
	SendAtToGps(ColdStart); // GPS冷启动
	HAL_Delay(100);
	SendAtToGps(GPSandBEIDOU); // GPS+BEIDOU
	HAL_Delay(100);
	SendAtToGps(OpenSBAS); // 开启SBAS 功能
	HAL_Delay(100);
	SendAtToGps(OpenBEIDOU32); // 开启BEIDOU
	// usleep(100);
	// SendAtToGps(SetNMEA41); // 设置 NMEA 4.1
	HAL_Delay(100);
	SendAtToGps(delay1sNMEA); // 配置输出 NMEA 消息的间隔 0.5s
	HAL_Delay(100);
	SendAtToGps(EnableRMC); // 设置 NMEA 语句输出使能  使能RMC
	HAL_Delay(100);
}
/*************************************
功能：GPSRMC数据解析
作者：xinxue
日期：2023.8.31
参数：无
返回值：无
**************************************/
void AnalysisRMC(rmc_data *pRecRMC, char *RX_BUF) // GPSRMC数据解析
{
	int i, n = 0;

	for (i = 0; RX_BUF[i] != '\r'; i++)
	{
		if (RX_BUF[i] == ',')
		{
			//printf("i :%d, n : %d next buffer:%c \n",i,n,RX_BUF[i+1]);
			n++;
			i++; // 跳过 “，”
			// strncpy(sub, string+12,13);   将string从string[12]开始，截取13个复制到sub中
			if (n == 1) //
			{
				if(RX_BUF[i] == ',') {
					pRecRMC->time[0] = '\0';
					i--;
				}else 
				{
					strncpy(pRecRMC->time, RX_BUF + i, 10);
					pRecRMC->time[10] = '\0';
					i = i + 9;
					//printf("pRecRMC->time: %s",pRecRMC->time);
				}
			} // i=i+10;目的是为了减少循环次数，提高效率
			else if (n == 2)
			{
				if(RX_BUF[i] == ',') {
					pRecRMC->state[0] = '\0';
					i--;
				}
				else
				{
					strncpy(pRecRMC->state, RX_BUF + i, 1);
					pRecRMC->state[1] = '\0';
					//printf("pRecRMC->state: %s",pRecRMC->state);
				}
			}
			else if (n == 3)
			{
				if(RX_BUF[i] == ',') {
					pRecRMC->lat[0] = '\0';
					i--;
				}
				else
				{
					strncpy(pRecRMC->lat, RX_BUF + i, 9);
					pRecRMC->lat[9] = '\0';
					i = i + 8;
				}
			}
			else if (n == 4)
			{
				if(RX_BUF[i] == ',') {
					i--;
				}
			}
			else if (n == 5)
			{
				if(RX_BUF[i] == ',') {
					pRecRMC->lng[0] = '\0';
					i--;
				}else
				{
					strncpy(pRecRMC->lng, RX_BUF + i, 10);
					pRecRMC->lng[10] = '\0';
					i = i + 9;
				}
			}
			else if (n == 6)
			{
				if(RX_BUF[i] == ',') {
					i--;
				}
			}
			else if (n == 7)
			{
				if(RX_BUF[i] == ',') {
					pRecRMC->speed[0] = '\0';
					i--;
				}else
				{
					
					int len = 0;
					while (1)
					{
						len++;
						if (RX_BUF[i + len] == ',')
							break;
					}
					strncpy(pRecRMC->speed, RX_BUF + i, len);
					pRecRMC->speed[len+1] = '\0';
					i = i + len - 1;
					// 速度转换成字符串
					if (len > 1)
					{
						pRecRMC->speed_f = atof(pRecRMC->speed);
						pRecRMC->speed_f *= 1.852;
						// printf("hex speed:%f km/h\n", pRecRMC->speed_f);
					}
					else
					{
						pRecRMC->speed_f = 0;
					}
				}
			}
			else if (n == 9)
			{
				if(RX_BUF[i] == ',') {
					pRecRMC->date[0] = '\0';
					i--;
				}else
				{
					strncpy(pRecRMC->date, RX_BUF + i, 6);
					pRecRMC->date[6] = '\0';
					i = i + 5;
				}
			}
		}
	}
	//printf("pRecRMC: time:%s,state:%s,date:%s,speed:%f\n\n", pRecRMC->time, pRecRMC->state, pRecRMC->date, pRecRMC->speed_f);
}
/*************************************
功能：GPS解析数据显示
作者：xinxue
日期：2023.8.31
参数：无
返回值：无
**************************************/

// void GpsRMCdataShow()

//{
// usleep(400);
//		 AnalysisRMC(pRecRMC);
//
//		 LCD_ShowString(10,70,250,16,16,"UTC  :");
//		 LCD_ShowString(60,70,250,16,16, (uint8_t*)pRecRMC->time);
//
//		 LCD_ShowString(10,90,250,16,16,"state:");
//		 LCD_ShowString(60,90,250,16,16,(uint8_t*)pRecRMC->state);
//
//		 LCD_ShowString(10,110,250,16,16,"lat  :");
//		 LCD_ShowString(60,110,250,16,16,(uint8_t*)pRecRMC->lat);
//		 LCD_ShowString(150,110,250,16,16,(uint8_t*)pRecRMC->NS);
//
//		 LCD_ShowString(10,130,250,16,16,"lng  :");
//		 LCD_ShowString(60,130,250,16,16,(uint8_t*)pRecRMC->lng);
//		 LCD_ShowString(150,130,250,16,16,(uint8_t*)pRecRMC->WE);
//
// 	   LCD_ShowString(10,150,250,16,16,"date :");
//	   LCD_ShowString(60,150,250,16,16,(uint8_t*)pRecRMC->date);
//		 memset(pRecRMC,0, sizeof pRecRMC);    //清空接收缓存区
//}
// 1.任务处理函数
//static void *UartDemo_Task(const char *arg)
//{
//	(void)arg;

//	int i = 0;
//	int state = 0;
//	int checksum = 0;
//	char check_hex[2];
//	int check_i;
//	while (1)
//	{
//		int ret ;//= hi_uart_read_timeout(HI_UART_IDX_1, (unsigned char *)&USARTx_RX_BUF[i], 15, 1);
//		if (USARTx_RX_BUF[i] == '$')
//		{
//			strncpy(USARTx_RX_BUF, &USARTx_RX_BUF[i], ret);
//			i = ret;
//			state = 1;
//			printf("buffer:%s i=%d\n", USARTx_RX_BUF, i);
//		}
//		else if (state == 1)
//		{
//			int len = i + ret;
//			for (; i < len; i++)
//			{
//				if (USARTx_RX_BUF[i] == '\r')
//				{
//					// printf("all buffer:%s len:%d\n ", USARTx_RX_BUF, i);
//					// 校验位读取
//					checksum = 0;
//					for (int j = 1; j < i - 3; j++)
//					{
//						checksum = checksum ^ USARTx_RX_BUF[j];
//					}
//					// 保存校验位
//					check_hex[0] = USARTx_RX_BUF[i - 2];
//					check_hex[1] = USARTx_RX_BUF[i - 1];
//					check_i = strtol(check_hex, NULL, 16);
//					// printf("%d %d\n", checksum, check_i);
//					if (checksum == check_i) // 校验位正确
//						//AnalysisRMC(pRecRMC);
//					memset(USARTx_RX_BUF, 0, sizeof USARTx_RX_BUF); // 清空接收缓存区
//					i = 0;
//					state = 0;
//					break;
//				}
//			}
//			if (i >= 100)
//			{
//				printf("i>=100\n");
//				i = 0;
//				state = 0;
//			}
//		}

//		usleep(100);
//	}

//	return NULL;
//}


static uint32_t AHT20_Read(uint8_t* buffer, uint32_t buffLen)
{
		HAL_I2C_Master_Receive(&hi2c2,AHT20_READ_ADDR,buffer,buffLen,0xff);
    return HI_ERR_SUCCESS;
}

static uint32_t AHT20_Write(uint8_t* buffer, uint32_t buffLen)
{
    HAL_I2C_Master_Transmit(&hi2c2,AHT20_WRITE_ADDR,buffer,buffLen,0xff);

    return HI_ERR_SUCCESS;
}

// 发送获取状态命令
static uint32_t AHT20_StatusCommand(void)
{
    uint8_t statusCmd[] = { AHT20_CMD_STATUS };
    return AHT20_Write(statusCmd, sizeof(statusCmd));
}

// 发送软复位命令
static uint32_t AHT20_ResetCommand(void)
{
    uint8_t resetCmd[] = {AHT20_CMD_RESET};
    return AHT20_Write(resetCmd, sizeof(resetCmd));
}

// 发送初始化校准命令
static uint32_t AHT20_CalibrateCommand(void)
{
    uint8_t clibrateCmd[] = {AHT20_CMD_CALIBRATION, AHT20_CMD_CALIBRATION_ARG0, AHT20_CMD_CALIBRATION_ARG1};
    return AHT20_Write(clibrateCmd, sizeof(clibrateCmd));
}

// 读取温湿度值之前， 首先要看状态字的校准使能位Bit[3]是否为 1(通过发送0x71可以获取一个字节的状态字)，
// 如果不为1，要发送0xBE命令(初始化)，此命令参数有两个字节， 第一个字节为0x08，第二个字节为0x00。
uint32_t AHT20_Calibrate(void)
{
    uint32_t retval = 0;
    uint8_t buffer[AHT20_STATUS_RESPONSE_MAX];
    memset(&buffer, 0x0, sizeof(buffer));

    retval = AHT20_StatusCommand();
    if (retval != HI_ERR_SUCCESS) {
        return retval;
    }

    retval = AHT20_Read(buffer, sizeof(buffer));
    if (retval != HI_ERR_SUCCESS) {
        return retval;
    }

    if (AHT20_STATUS_BUSY(buffer[0]) || !AHT20_STATUS_CALI(buffer[0])) {
        retval = AHT20_ResetCommand();
        if (retval != HI_ERR_SUCCESS) {
            return retval;
        }
        HAL_Delay(AHT20_STARTUP_TIME);
        retval = AHT20_CalibrateCommand();
        HAL_Delay(AHT20_CALIBRATION_TIME);
        return retval;
    }

    return HI_ERR_SUCCESS;
}

// 发送 触发测量 命令，开始测量
uint32_t AHT20_StartMeasure(void)
{
    uint8_t triggerCmd[] = {AHT20_CMD_TRIGGER, AHT20_CMD_TRIGGER_ARG0, AHT20_CMD_TRIGGER_ARG1};
    return AHT20_Write(triggerCmd, sizeof(triggerCmd));
}

// 接收测量结果，拼接转换为标准值
uint32_t AHT20_GetMeasureResult(float* temp, float* humi)
{
    uint32_t retval = 0, i = 0;
    if (temp == NULL || humi == NULL) {
        return HI_ERR_FAILURE;
    }

    uint8_t buffer[AHT20_STATUS_RESPONSE_MAX];
    memset(&buffer, 0x0, sizeof(buffer));
    retval = AHT20_Read(buffer, sizeof(buffer));  // recv status command result
    if (retval != HI_ERR_SUCCESS) {
			return retval;
    }

    for (i = 0; AHT20_STATUS_BUSY(buffer[0]) && i < AHT20_MAX_RETRY; i++) {
        // printf("AHT20 device busy, retry %d/%d!\r\n", i, AHT20_MAX_RETRY);
        HAL_Delay(AHT20_MEASURE_TIME);
        retval = AHT20_Read(buffer, sizeof(buffer));  // recv status command result
        if (retval != HI_ERR_SUCCESS) {
            return retval;
        }
    }
    if (i >= AHT20_MAX_RETRY) {
        printf("AHT20 device always busy!\r\n");
        return HI_ERR_SUCCESS;
    }

    uint32_t humiRaw = buffer[1];
    humiRaw = (humiRaw << 8) | buffer[2];
    humiRaw = (humiRaw << 4) | ((buffer[3] & 0xF0) >> 4);
    *humi = humiRaw / (float)AHT20_RESOLUTION * 100;

    uint32_t tempRaw = buffer[3] & 0x0F;
    tempRaw = (tempRaw << 8) | buffer[4];
    tempRaw = (tempRaw << 8) | buffer[5];
    *temp = tempRaw / (float)AHT20_RESOLUTION * 200 - 50;
    // printf("humi = %05X, %f, temp= %05X, %f\r\n", humiRaw, *humi, tempRaw, *temp);
    return HI_ERR_SUCCESS;
}

void OH_TransmitHandle(rmc_data *pRecRMC, uint8_t *data)
{
    sprintf(data, "$OH,%s,%s,%s,%s,%s,%s,%f,*", pRecRMC->time, pRecRMC->state, pRecRMC->lat, pRecRMC->lng, pRecRMC->speed, pRecRMC->date, pRecRMC->temp);
    // 校验位计算
    pRecRMC->SumCheck = 0;
    for (int i = 1; data[i] != '*'; i++)
    {
        pRecRMC->SumCheck = pRecRMC->SumCheck ^ data[i];
    }
    // 融合数据
    sprintf(data + strlen(data), "%x", (unsigned char)pRecRMC->SumCheck);
    uint8_t test_data[100] = {0};
		sprintf(test_data, "%s \n",data);
		HAL_UART_Transmit(&huart1,test_data,100,0xff);
}